package TestDemo;

import thread.Synchronized_Class;

import java.util.PriorityQueue;
import java.util.TimerTask;


/**
 * Created with IntelliJ IDEA
 * Description:
 * User:34398
 * Date:2024-07-28
 * Time:15:17
 */


/**
 * 我们会使用优先级队列来判断那个任务最紧急需要先完成，所以需要实现Compareble，
 * 然后重写compareTo方法，用时间戳进行大小比较
 * 优先级队列中，存放的是一个一个要执行的任务
 */
class MyTimerTask implements Comparable<MyTimerTask> {

    //用绝对时间——时间戳来表示时间间隔
    long time;

    //要执行的任务
    Runnable runnable;

    //构造方法
    public MyTimerTask(Runnable runnable, long delay) {

        //执行时间等于当前时间+延迟时间大小
        this.time = System.currentTimeMillis() + delay;

        this.runnable = runnable;
    }

    //用于执行任务
    public void run() {
        runnable.run();
    }

    //获取需要执行的任务的执行时间,等一下有用
    public long getTime() {
        return time;
    }

    @Override
    public int compareTo(MyTimerTask o) {
        //创建一个小根堆，时间到的先执行
        return (int) (this.time - o.time);
    }
}


class MyTimer {

    //把schedule的任务放到这里，然后去除优先级大的任务，判断时间，是否需要执行
    PriorityQueue<MyTimerTask> queue = new PriorityQueue<>();
    //创建一个锁对象
    private Object locker = new Object();

    public void schedule(Runnable runnable, long delay) {

        //涉及优先级队列的读写操作，需要加锁保证线程安全
        synchronized (locker) {
            //把runnable和delay封装到myTimerTask中
            MyTimerTask myTimerTask = new MyTimerTask(runnable, delay);

            //放入优先级队列
            queue.offer(myTimerTask);

            //通知唤醒myTimer创建的线程
            locker.notify();
        }
    }

    //构造方法，一旦创建这个实例，开始在优先级队列里面循环获取方法执行（如果到达要执行的时机）
    public MyTimer() {
        Thread t = new Thread(() -> {

            while (true) {
                try {
                    //下面涉及对优先级队列的读写操作，需要保证线程安全
                    synchronized (locker) {

                        //目前没有任务，就一直睡，直到schedule了新的任务
                        while (queue.isEmpty()) {
                            locker.wait();
                        }

                        //有了任务，先看看当前需不需要执行
                        MyTimerTask task=queue.peek();

                        //时间已经到了，或者超时了，就执行
                        if(System.currentTimeMillis()>=task.time){
                            task.run();
                            //一处执行完的任务
                            queue.poll();
                        }else{
                            //没到时间，就睡到任务执行的时候
                            locker.wait(task.time-System.currentTimeMillis());
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        //启动线程
        t.start();
    }
}

public class Test {
    public static void main(String[] args) throws InterruptedException {
        MyTimer myTimer = new MyTimer();
        myTimer.schedule(() -> {
            System.out.println("hello 1000");
        }, 1000);

        myTimer.schedule(() -> {
            System.out.println("hello 2000");
        }, 2000);

        myTimer.schedule(() -> {
            System.out.println("hello 3000");
        }, 3000);

        System.out.println("程序开始运行");
    }
}
